package com.castle.utils;

import org.apache.commons.lang.StringUtils;

import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 *  SHA256WithRSA 工具类
 * @author  castle
 */
public class Rsa2SignUtils {
	private static final String KEY_ALGORITHM = "RSA";

	public static final String SIGNATURE_ALGORITHM = "SHA256withRSA";


	/**
	 * 解码PrivateKey
	 * @param key
	 * @return
	 */
	public static PrivateKey getPrivateKey(String key) {
		try {
			byte[] byteKey = Base64.getDecoder().decode(key);
			PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey);
			KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

			return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	/**
	 * 签名
	 * @param key	私钥
	 * @param requestData	请求参数
	 * @return
	 */
	public static String sign(String key, String requestData){
		String signature = null;
		byte[] signed = null;
		try {
			PrivateKey privateKey = getPrivateKey(key);

			Signature Sign = Signature.getInstance(SIGNATURE_ALGORITHM);
			Sign.initSign(privateKey);
			Sign.update(requestData.getBytes());
			signed = Sign.sign();

			signature = Base64.getEncoder().encodeToString(signed);
			System.out.println("===签名结果："+signature);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return signature;
	}


	/**
	 * 处理输入参数
	 * @param map
	 * @return
	 */
	public static String initParamMap(Map<String,Object> map){
		//构造签名参数集合
		Map<String,Object> signParamMap=new HashMap<>();
		if(map!=null && !map.isEmpty()){
			for(String key:map.keySet()){
				// 筛选 非null且非空的参数参与签名
				if(map.get(key)!=null && StringUtils.isNotEmpty(map.get(key).toString())){
					signParamMap.put(key,map.get(key));
				}
			}
		}

		//排序 signParamMap的key值按照ASCII码升序排列
		TreeMap<String,Object> treeMap=new TreeMap();
		for(String key:signParamMap.keySet()){
			treeMap.put(key,signParamMap.get(key));
		}

		//拼接 将排序后的参数与其值，组合成“参数=参数值”的格式，并且把这些参数用&字符连接来，此时生成的字符串为待签名字符串
		StringBuilder sb=new StringBuilder();
		for(String key:treeMap.keySet()){
			sb.append(key+"="+treeMap.get(key)+"&");
		}
		sb=new StringBuilder(sb.toString().substring(0,sb.lastIndexOf("&")));
		return sb.toString();
	}
}
